<template>
  <div class="chat-window">
    <div class="bottom">
      <!-- GPT 使用手册，当没有选中会话时显示 -->
      <GptManual v-if="showManual" @sendMessage="handleSendMessage" />

      <!-- 聊天内容区域 -->
      <div class="chat-content" id="chatContent">
        <div class="chat-wrapper" v-for="item in chatList" :key="item.messageId">
          <!-- 展示对方消息 -->
          <div class="chat-friend" v-if="item.messageDirection !== 0">
            <div class="info-time">
              <span>{{ item.createTime }}</span> <!-- 显示消息的时间 -->
            </div>
            <div v-html="renderContent(item.content)" class="chat-text"></div> <!-- 渲染消息内容 -->
          </div>
          <!-- 展示自己的消息 -->
          <div class="chat-me" v-else>
            <div class="info-time">
              <span>{{ item.createTime }}</span> <!-- 显示消息的时间 -->
            </div>
            <div v-html="renderContent(item.content)" class="chat-text"></div> <!-- 渲染消息内容 -->
          </div>
        </div>
        <!-- GPT 回复内容 -->
        <div v-if="answerContent !== ''" class="chat-wrapper">
          <div class="chat-friend">
            <div v-html="renderContent(answerContent)" class="chat-text"></div>
          </div>
        </div>
      </div>

      <!-- 输入框区域 -->
      <div class="chatInputs">
        <input class="inputs" v-model="inputMsg" @keyup.enter="sendText" /> <!-- 绑定输入框数据并监听回车事件 -->
        <div class="send boxinput" @click="sendText">
          <img src="@/assets/img/rocket.png" alt="" /> <!-- 发送按钮 -->
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
// 引入必要的组件和工具函数
import GptManual from '@/components/gpt/GptManual.vue';
import { getGptMessage } from "@/api/getSession.ts";
import { nextTick, onMounted, reactive, ref, watch } from 'vue';
import { getCurrentDateTime } from '@/components/utils/FormatChecker';
import { useUserStore } from "@/stores/user";
import { fetchEventSource } from "@microsoft/fetch-event-source";
import { Marked } from "marked";
import { markedHighlight } from "marked-highlight";
import hljs from 'highlight.js';
import '@/assets/css/atom-one-dark.css';

// 定义事件和属性
const emit = defineEmits(['convCardSort', 'updateConversationList']);
const props = defineProps({
  conversationInfo: {
    type: Object,
    required: true,
  },
});

// 核心变量
const userStore = reactive(useUserStore());  // 用户状态
const chatList = ref([]);  // 聊天记录列表
const inputMsg = ref("");  // 用户输入的消息
const answerContent = ref('');  // GPT 回复的内容
const showManual = ref(true);  // 控制 GPT 使用手册显示状态

// 初始化时获取聊天记录
onMounted(() => {
  getFriendChatMsg();
});

// 监听会话信息变化，根据会话状态调整显示内容
watch(() => props.conversationInfo, (newVal) => {
  showManual.value = !newVal.conversationId;  // 如果没有会话ID，显示手册
  if (!newVal.conversationId) {
    chatList.value = [];  // 清空聊天内容
  } else {
    getFriendChatMsg(newVal.conversationId);  // 获取新的会话记录
  }
});

// 设置 markdown 解析器及其参数，用于高亮代码
const marked = new Marked(
    markedHighlight({
      langPrefix: 'hljs language-',  // 设置代码高亮的类名前缀
      highlight(code, lang) {
        const language = hljs.getLanguage(lang) ? lang : 'plaintext';  // 如果语言不支持，使用纯文本
        return hljs.highlight(code, { language }).value;  // 高亮代码
      }
    })
);

// 渲染消息内容为 HTML
function renderContent(value) {
  return marked.parse(value);  // 将 markdown 内容转换为 HTML
}

// 获取当前会话的聊天记录
function getFriendChatMsg(conversationId = props.conversationInfo.conversationId) {
  getGptMessage(conversationId).then((res) => {
    chatList.value = res;  // 设置聊天记录
    nextTick(scrollBottom);  // 滚动到聊天窗口底部
  });
}

// 发送消息到聊天列表
function sendMsg(msg) {
  chatList.value.push(msg);  // 将消息加入聊天记录
  nextTick(scrollBottom);  // 滚动到底部
}

// 滚动聊天窗口到底部
function scrollBottom() {
  const chatContent = document.getElementById('chatContent');
  chatContent.scrollTop = chatContent.scrollHeight;  // 滚动到最底部
}

// 发送文本消息
function sendText() {
  if (inputMsg.value) {
    const chatMsg = {
      messageDirection: 0,  // 设置消息方向为自己发送
      content: inputMsg.value,  // 消息内容
      createTime: getCurrentDateTime(),  // 消息发送时间
    };
    sendMsg(chatMsg);  // 发送消息

    showManual.value = false;  // 隐藏手册

    // 如果是旧会话，执行 convCardSort
    if (props.conversationInfo.conversationId) {
      emit('convCardSort', props.conversationInfo.conversationId);  // 通知父组件会话排序
    }

    ask(inputMsg.value);  // 向 GPT 发送请求
    inputMsg.value = "";  // 清空输入框
  } else {
    this.$message({
      message: "消息不能为空哦~",
      type: "warning",
    });
  }
}

// 请求 GPT 响应并处理流式返回
function ask(prompt) {
  const controller = new AbortController();  // 创建 AbortController，用于取消请求

  fetchEventSource("http://localhost:8080/gpt/chat", {
    method: 'POST',
    headers: {
      Accept: "text/event-stream",  // 期待服务器返回流式数据
      "Content-Type": "application/json",
      Token: userStore.token,
    },
    body: JSON.stringify({
      useToken: userStore.useToken,
      conversationId: props.conversationInfo.conversationId,  // 会话ID，可能为空
      prompt: prompt,  // 用户输入的内容
    }),
    signal: controller.signal,  // 绑定取消信号
    openWhenHidden: true,
    onopen() {},
    onmessage(event) {
      const responseData = JSON.parse(event.data);  // 解析服务器返回的数据

      if (responseData.endOfStream) {
        // 如果是流的结束，更新会话列表并通知父组件排序
        emit('updateConversationList', {
          conversationId: responseData.conversationId,
          conversationName: responseData.conversationName,
        });
        props.conversationInfo.conversationId = responseData.conversationId;
      } else {
        answerContent.value += responseData.content;  // 拼接 GPT 的回复内容
        nextTick(scrollBottom);  // 确保滚动到底部
      }
    },
    onclose() {
      sendMsg({
        messageDirection: 1,  // 设置消息方向为对方发送
        content: answerContent.value,  // GPT 的最终回复内容
        createTime: getCurrentDateTime(),  // 消息发送时间
      });
      answerContent.value = '';  // 清空 GPT 的回复内容
      controller.abort();  // 取消请求
    },
    onerror() {
      answerContent.value = '';  // 清空 GPT 的回复内容
      controller.abort();  // 取消请求
    },
  });
}

// 处理来自 GPT 使用手册的消息
function handleSendMessage(message) {
  sendMsg({
    messageDirection: 0,  // 设置消息方向为自己发送
    content: message,  // 消息内容
    createTime: getCurrentDateTime(),  // 消息发送时间
  });

  showManual.value = false;  // 隐藏手册

  ask(message);  // 向 GPT 发送请求
}
</script>


<style lang="scss" scoped>

.chat-window {
  width: 100%;
  height: 100%;
  margin-left: 20px;
  .bottom {
    width: 100%;
    height: 86vh;
    background-color: #9facbf; /* 深色背景 */
    border-radius: 20px;
    border: 1px solid #444449; /* 边框颜色调整为深灰色 */
    padding: 20px;
    box-sizing: border-box;
    position: relative;
    .chat-content {
      width: 100%;
      height: 85%;
      overflow-y: scroll;
      padding: 20px;
      box-sizing: border-box;
      &::-webkit-scrollbar {
        width: 0; /* Safari,Chrome 隐藏滚动条 */
        height: 0; /* Safari,Chrome 隐藏滚动条 */
        display: none; /* 移动端、pad 上Safari，Chrome，隐藏滚动条 */
      }
      .chat-wrapper {
        position: relative;
        word-break: break-all;
        .chat-friend {
          width: 100%;
          float: left;
          margin-bottom: 20px;
          display: flex;
          flex-direction: column;
          justify-content: flex-start;
          align-items: flex-start;
          .chat-text {
            max-width: 90%;
            padding: 3px 20px;
            border-radius: 20px 20px 20px 5px;
            background-color: #444449; /* 调整气泡背景颜色为深灰色 */
            color: #e1e1e1; /* 文本颜色调整为浅灰色 */
            &:hover {
              background-color: #5a5a5f; /* 悬停时背景色稍微变亮 */
            }
          }
          .info-time {
            margin: 10px 0;
            color: #a1a1a1; /* 时间信息颜色调整为灰色 */
            font-size: 14px;
            span:last-child {
              color: rgb(121, 124, 135);
              margin-left: 10px;
              vertical-align: middle;
            }
          }
        }
        .chat-me {
          width: 100%;
          float: right;
          margin-bottom: 20px;
          position: relative;
          display: flex;
          flex-direction: column;
          justify-content: flex-end;
          align-items: flex-end;
          .chat-text {
            float: right;
            max-width: 90%;
            padding: 3px 20px;
            border-radius: 20px 20px 5px 20px;
            background-color: olivedrab; /* 用户气泡背景颜色调整为蓝色 */
            color: #ffffff; /* 文本颜色调整为白色 */
          }
          .info-time {
            margin: 10px 0;
            color: #a1a1a1; /* 时间信息颜色调整为灰色 */
            font-size: 14px;
            display: flex;
            justify-content: flex-end;
            span {
              line-height: 30px;
            }
            span:first-child {
              color: rgb(121, 124, 135);
              margin-right: 10px;
              vertical-align: middle;
            }
          }
        }
      }
    }
    .chatInputs {
      width: 90%;
      position: absolute;
      bottom: 0;
      margin: 3%;
      display: flex;
      .boxinput {
        width: 50px;
        height: 50px;
        border-radius: 15px;
        border: 1px solid #101c2b; /* 边框颜色调整为深灰色 */
        position: relative;
        cursor: pointer;
        img {
          width: 30px;
          height: 30px;
          position: absolute;
          left: 50%;
          top: 50%;
          transform: translate(-50%, -50%);
        }
      }
      .inputs {
        width: 90%;
        height: 50px;
        background-color: #3a3b3e; /* 输入框背景颜色调整为深灰色 */
        border-radius: 15px;
        border: 2px solid #2a5fb0; /* 边框颜色调整为蓝色 */
        padding: 10px;
        box-sizing: border-box;
        transition: 0.2s;
        font-size: 15px;
        color: #e1e1e1; /* 文本颜色调整为浅灰色 */
        font-weight: 100;
        margin: 0 20px;
        &:focus {
          outline: none;
        }
      }
      .send {
        background-color: olivedrab; /* 发送按钮背景颜色调整为蓝色 */
        border: 0;
        transition: 0.3s;
        box-shadow: 0 0 5px 0 #56b6c2;
        &:hover {
          box-shadow: 0 0 10px 0 #101c2b;
        }
      }
    }
  }
}
</style>
